home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / cyberbal.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  15KB  |  606 lines

  1. /***************************************************************************
  2.  
  3.     vidhrdw/cyberbal.c
  4.  
  5.     Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bit  15    = horizontal flip
  15.             Bits 11-14 = palette
  16.             Bits  0-12 = image index
  17.  
  18.  
  19.     Motion Object encoding
  20.     ----------------------
  21.         4 16-bit words are used
  22.  
  23.         Word 1:
  24.             Bit  15    = horizontal flip
  25.             Bits  0-14 = image index
  26.  
  27.         Word 2:
  28.             Bits  7-15 = Y position
  29.             Bits  0-3  = height in tiles
  30.  
  31.         Word 3:
  32.             Bits  3-10 = link to the next image to display
  33.  
  34.         Word 4:
  35.             Bits  6-14 = X position
  36.             Bit   4    = use current X position + 16 for next sprite
  37.             Bits  0-3  = palette
  38.  
  39.  
  40.     Alpha layer encoding
  41.     --------------------
  42.         1 16-bit word is used
  43.  
  44.         Word 1:
  45.             Bit  15    = horizontal flip
  46.             Bit  12-14 = palette
  47.             Bits  0-11 = image index
  48.  
  49. ***************************************************************************/
  50.  
  51. #include "driver.h"
  52. #include "machine/atarigen.h"
  53. #include "vidhrdw/generic.h"
  54.  
  55. #define XCHARS 42
  56. #define YCHARS 30
  57.  
  58. #define XDIM (XCHARS*16)
  59. #define YDIM (YCHARS*8)
  60.  
  61.  
  62.  
  63. /*************************************
  64.  *
  65.  *    Structures
  66.  *
  67.  *************************************/
  68.  
  69. struct mo_params
  70. {
  71.     int xhold;
  72.     struct osd_bitmap *bitmap;
  73. };
  74.  
  75.  
  76.  
  77. /*************************************
  78.  *
  79.  *    Globals we own
  80.  *
  81.  *************************************/
  82.  
  83. UINT8 *cyberbal_playfieldram_1;
  84. UINT8 *cyberbal_playfieldram_2;
  85.  
  86.  
  87.  
  88. /*************************************
  89.  *
  90.  *    Statics
  91.  *
  92.  *************************************/
  93.  
  94. static struct atarigen_pf_state pf_state;
  95. static UINT8 current_slip;
  96. static UINT8 *active_palette;
  97.  
  98.  
  99.  
  100. /*************************************
  101.  *
  102.  *    Prototypes
  103.  *
  104.  *************************************/
  105.  
  106. static const UINT8 *update_palette(void);
  107.  
  108. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  109. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  110.  
  111. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  112. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  113.  
  114.  
  115.  
  116. /*************************************
  117.  *
  118.  *    Video system start
  119.  *
  120.  *************************************/
  121.  
  122. int cyberbal_vh_start(void)
  123. {
  124.     static struct atarigen_mo_desc mo_desc =
  125.     {
  126.         256,                /* maximum number of MO's */
  127.         8,                    /* number of bytes per MO entry */
  128.         2,                    /* number of bytes between MO words */
  129.         0,                    /* ignore an entry if this word == 0xffff */
  130.         2, 3, 0xff,            /* link = (data[linkword] >> linkshift) & linkmask */
  131.         0                    /* reverse order */
  132.     };
  133.  
  134.     static struct atarigen_pf_desc pf_desc =
  135.     {
  136.         16, 8,                /* width/height of each tile */
  137.         64, 64                /* number of tiles in each direction */
  138.     };
  139.  
  140.     /* reset statics */
  141.     memset(&pf_state, 0, sizeof(pf_state));
  142.     current_slip = 0;
  143.  
  144.     /* initialize the playfield */
  145.     if (atarigen_pf_init(&pf_desc))
  146.         return 1;
  147.  
  148.     /* initialize the motion objects */
  149.     if (atarigen_mo_init(&mo_desc))
  150.     {
  151.         atarigen_pf_free();
  152.         return 1;
  153.     }
  154.  
  155.     return 0;
  156. }
  157.  
  158.  
  159.  
  160. /*************************************
  161.  *
  162.  *    Video system shutdown
  163.  *
  164.  *************************************/
  165.  
  166. void cyberbal_vh_stop(void)
  167. {
  168.     atarigen_pf_free();
  169.     atarigen_mo_free();
  170. }
  171.  
  172.  
  173.  
  174. /*************************************
  175.  *
  176.  *    Palette tweaker
  177.  *
  178.  *************************************/
  179.  
  180. INLINE void set_palette_entry(int entry, UINT16 value)
  181. {
  182.     int r, g, b;
  183.  
  184.     r = ((value >> 9) & 0x3e) | ((value >> 15) & 1);
  185.     g = ((value >> 4) & 0x3e) | ((value >> 15) & 1);
  186.     b = ((value << 1) & 0x3e) | ((value >> 15) & 1);
  187.  
  188.     r = (r << 2) | (r >> 4);
  189.     g = (g << 2) | (g >> 4);
  190.     b = (b << 2) | (b >> 4);
  191.  
  192.     palette_change_color(entry, r, g, b);
  193. }
  194.  
  195.  
  196.  
  197. /*************************************
  198.  *
  199.  *    Screen switcher
  200.  *
  201.  *************************************/
  202.  
  203. void cyberbal_set_screen(int which)
  204. {
  205.     int i;
  206.  
  207.     /* update the video memory areas */
  208.     atarigen_playfieldram = which ? cyberbal_playfieldram_2 : cyberbal_playfieldram_1;
  209.     atarigen_playfieldram_size = 0x2000;
  210.     atarigen_alpharam = atarigen_playfieldram + atarigen_playfieldram_size;
  211.     atarigen_alpharam_size = 0x1000;
  212.     atarigen_spriteram = atarigen_alpharam + atarigen_alpharam_size;
  213.     atarigen_spriteram_size = 0x1000;
  214.  
  215.     /* pick the active palette */
  216.     active_palette = which ? paletteram_2 : paletteram;
  217.  
  218.     /* re-init the palette */
  219.     for (i = 0; i < 2048; i++)
  220.         set_palette_entry(i, READ_WORD(&active_palette[i * 2]));
  221.  
  222.     /* invalidate the screen */
  223.     memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  224. }
  225.  
  226.  
  227.  
  228. /*************************************
  229.  *
  230.  *    Playfield RAM write handlers
  231.  *
  232.  *************************************/
  233.  
  234. WRITE_HANDLER( cyberbal_playfieldram_1_w )
  235. {
  236.     int oldword = READ_WORD(&cyberbal_playfieldram_1[offset]);
  237.     int newword = COMBINE_WORD(oldword, data);
  238.  
  239.     if (oldword != newword)
  240.     {
  241.         WRITE_WORD(&cyberbal_playfieldram_1[offset], newword);
  242.         if (cyberbal_playfieldram_1 == atarigen_playfieldram)
  243.             atarigen_pf_dirty[offset / 2] = 0xff;
  244.     }
  245. }
  246.  
  247.  
  248. WRITE_HANDLER( cyberbal_playfieldram_2_w )
  249. {
  250.     int oldword = READ_WORD(&cyberbal_playfieldram_2[offset]);
  251.     int newword = COMBINE_WORD(oldword, data);
  252.  
  253.     if (oldword != newword)
  254.     {
  255.         WRITE_WORD(&cyberbal_playfieldram_2[offset], newword);
  256.         if (cyberbal_playfieldram_2 == atarigen_playfieldram)
  257.             atarigen_pf_dirty[offset / 2] = 0xff;
  258.     }
  259. }
  260.  
  261.  
  262.  
  263. /*************************************
  264.  *
  265.  *    Palette RAM write handlers
  266.  *
  267.  *************************************/
  268.  
  269. WRITE_HANDLER( cyberbal_paletteram_1_w )
  270. {
  271.     int oldword = READ_WORD(&paletteram[offset]);
  272.     int newword = COMBINE_WORD(oldword, data);
  273.  
  274.     if (oldword != newword)
  275.     {
  276.         WRITE_WORD(&paletteram[offset], newword);
  277.         if (paletteram == active_palette)
  278.             set_palette_entry(offset / 2, newword);
  279.     }
  280. }
  281.  
  282. READ_HANDLER( cyberbal_paletteram_1_r )
  283. {
  284.     return READ_WORD(&paletteram[offset]);
  285. }
  286.  
  287.  
  288. WRITE_HANDLER( cyberbal_paletteram_2_w )
  289. {
  290.     int oldword = READ_WORD(&paletteram_2[offset]);
  291.     int newword = COMBINE_WORD(oldword, data);
  292.  
  293.     if (oldword != newword)
  294.     {
  295.         WRITE_WORD(&paletteram_2[offset], newword);
  296.         if (paletteram_2 == active_palette)
  297.             set_palette_entry(offset / 2, newword);
  298.     }
  299. }
  300.  
  301. READ_HANDLER( cyberbal_paletteram_2_r )
  302. {
  303.     return READ_WORD(&paletteram_2[offset]);
  304. }
  305.  
  306.  
  307.  
  308. /*************************************
  309.  *
  310.  *    Periodic scanline updater
  311.  *
  312.  *************************************/
  313.  
  314. void cyberbal_scanline_update(int scanline)
  315. {
  316.     UINT16 *base = (UINT16 *)&atarigen_alpharam[((scanline / 8) * 64 + 47) * 2];
  317.  
  318.     /* keep in range */
  319.     if ((UINT8 *)base >= &atarigen_alpharam[atarigen_alpharam_size])
  320.         return;
  321.  
  322.     /* update the playfield with the previous parameters */
  323.     atarigen_pf_update(&pf_state, scanline);
  324.  
  325.     /* update the MOs with the previous parameters */
  326.     atarigen_mo_update(atarigen_spriteram, current_slip, scanline);
  327.  
  328.     /* update the current parameters */
  329.     if (!(base[3] & 1))
  330.         pf_state.param[0] = (base[3] >> 1) & 7;
  331.     if (!(base[4] & 1))
  332.         pf_state.hscroll = 2 * (((base[4] >> 7) + 4) & 0x1ff);
  333.     if (!(base[5] & 1))
  334.     {
  335.         /* a new vscroll latches the offset into a counter; we must adjust for this */
  336.         int offset = scanline + 8;
  337.         if (offset >= 256)
  338.             offset -= 256;
  339.         pf_state.vscroll = ((base[5] >> 7) - offset) & 0x1ff;
  340.     }
  341.     if (!(base[6] & 1))
  342.         pf_state.param[1] = (base[6] >> 1) & 0xff;
  343.     if (!(base[7] & 1))
  344.         current_slip = (base[7] >> 3) & 0xff;
  345. }
  346.  
  347.  
  348.  
  349. /*************************************
  350.  *
  351.  *    Main refresh
  352.  *
  353.  *************************************/
  354.  
  355. void cyberbal_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  356. {
  357.     struct mo_params modata;
  358.     const struct GfxElement *gfx;
  359.     int x, y, offs;
  360.  
  361.     /* update the palette, and mark things dirty */
  362.     if (update_palette())
  363.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  364.  
  365.     /* draw the playfield */
  366.     memset(atarigen_pf_visit, 0, 64*64);
  367.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  368.  
  369.     /* draw the motion objects */
  370.     modata.xhold = 1000;
  371.     modata.bitmap = bitmap;
  372.     atarigen_mo_process(mo_render_callback, &modata);
  373.  
  374.     /* draw the alphanumerics */
  375.     gfx = Machine->gfx[2];
  376.     for (y = 0; y < YCHARS; y++)
  377.         for (x = 0, offs = y * 64; x < XCHARS; x++, offs++)
  378.         {
  379.             int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  380.             int code = data & 0xfff;
  381.             int hflip = data & 0x8000;
  382.             int color = (data >> 12) & 7;
  383.             drawgfx(bitmap, gfx, code, color, hflip, 0, 16 * x, 8 * y, 0, TRANSPARENCY_PEN, 0);
  384.         }
  385.  
  386.     /* update onscreen messages */
  387.     atarigen_update_messages();
  388. }
  389.  
  390.  
  391.  
  392. /*************************************
  393.  *
  394.  *    Palette management
  395.  *
  396.  *************************************/
  397.  
  398. static const UINT8 *update_palette(void)
  399. {
  400.     UINT16 pf_map[16 * 8], mo_map[16], al_map[8];
  401.     const unsigned int *usage;
  402.     int i, j, x, y, offs;
  403.  
  404.     /* reset color tracking */
  405.     memset(mo_map, 0, sizeof(mo_map));
  406.     memset(pf_map, 0, sizeof(pf_map));
  407.     memset(al_map, 0, sizeof(al_map));
  408.     palette_init_used_colors();
  409.  
  410.     /* update color usage for the playfield */
  411.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  412.  
  413.     /* update color usage for the mo's */
  414.     atarigen_mo_process(mo_color_callback, mo_map);
  415.  
  416.     /* update color usage for the alphanumerics */
  417.     usage = Machine->gfx[2]->pen_usage;
  418.     for (y = 0; y < YCHARS; y++)
  419.         for (x = 0, offs = y * 64; x < XCHARS; x++, offs++)
  420.         {
  421.             int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  422.             int code = data & 0xfff;
  423.             int color = (data >> 12) & 7;
  424.             al_map[color] |= usage[code];
  425.         }
  426.  
  427.     /* rebuild the playfield palette */
  428.     for (i = 0; i < 16 * 8; i++)
  429.     {
  430.         UINT16 used = pf_map[i];
  431.         if (used)
  432.             for (j = 0; j < 16; j++)
  433.                 if (used & (1 << j))
  434.                     palette_used_colors[i * 16 + j] = PALETTE_COLOR_USED;
  435.     }
  436.  
  437.     /* rebuild the motion object palette */
  438.     for (i = 0; i < 16; i++)
  439.     {
  440.         UINT16 used = mo_map[i];
  441.         if (used)
  442.         {
  443.             palette_used_colors[0x600 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  444.             for (j = 1; j < 16; j++)
  445.                 if (used & (1 << j))
  446.                     palette_used_colors[0x600 + i * 16 + j] = PALETTE_COLOR_USED;
  447.         }
  448.     }
  449.  
  450.     /* rebuild the alphanumerics palette */
  451.     for (i = 0; i < 8; i++)
  452.     {
  453.         UINT16 used = al_map[i];
  454.         if (used)
  455.         {
  456.             palette_used_colors[0x780 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  457.             for (j = 1; j < 16; j++)
  458.                 if (used & (1 << j))
  459.                     palette_used_colors[0x780 + i * 16 + j] = PALETTE_COLOR_USED;
  460.         }
  461.     }
  462.  
  463.     /* recalc */
  464.     return palette_recalc();
  465. }
  466.  
  467.  
  468.  
  469. /*************************************
  470.  *
  471.  *    Playfield palette
  472.  *
  473.  *************************************/
  474.  
  475. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  476. {
  477.     UINT16 *colormap = (UINT16 *)param + 16 * state->param[0];
  478.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  479.     int x, y;
  480.  
  481.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  482.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  483.         {
  484.             int offs = y * 64 + x;
  485.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  486.             int code = data & 0x1fff;
  487.             int color = (data >> 11) & 15;
  488.             colormap[color] |= usage[code];
  489.  
  490.             /* also mark unvisited tiles dirty */
  491.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 0xff;
  492.         }
  493. }
  494.  
  495.  
  496.  
  497. /*************************************
  498.  *
  499.  *    Playfield rendering
  500.  *
  501.  *************************************/
  502.  
  503. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  504. {
  505.     const struct GfxElement *gfx = Machine->gfx[0];
  506.     int colorbase = 16 * state->param[0];
  507.     struct osd_bitmap *bitmap = param;
  508.     int x, y;
  509.  
  510.     /* first update any tiles whose color is out of date */
  511.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  512.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  513.         {
  514.             int offs = y * 64 + x;
  515.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  516.             int color = colorbase + ((data >> 11) & 15);
  517.  
  518.             if (atarigen_pf_dirty[offs] != color)
  519.             {
  520.                 int code = data & 0x1fff;
  521.                 int hflip = data & 0x8000;
  522.  
  523.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, 16 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  524.                 atarigen_pf_dirty[offs] = color;
  525.             }
  526.  
  527.             /* track the tiles we've visited */
  528.             atarigen_pf_visit[offs] = 1;
  529.         }
  530.  
  531.     /* then blast the result */
  532.     x = -state->hscroll;
  533.     y = -state->vscroll;
  534.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  535. }
  536.  
  537.  
  538.  
  539. /*************************************
  540.  *
  541.  *    Motion object palette
  542.  *
  543.  *************************************/
  544.  
  545. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  546. {
  547.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  548.     UINT16 *colormap = param;
  549.     UINT16 temp = 0;
  550.     int y;
  551.  
  552.     int code = data[0] & 0x7fff;
  553.     int vsize = (data[1] & 15) + 1;
  554.     int color = data[3] & 0x0f;
  555.  
  556.     for (y = 0; y < vsize; y++)
  557.         temp |= usage[code++];
  558.     colormap[color] |= temp;
  559. }
  560.  
  561.  
  562.  
  563. /*************************************
  564.  *
  565.  *    Motion object rendering
  566.  *
  567.  *************************************/
  568.  
  569. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  570. {
  571.     const struct GfxElement *gfx = Machine->gfx[1];
  572.     struct mo_params *modata = param;
  573.     struct osd_bitmap *bitmap = modata->bitmap;
  574.  
  575.     /* extract data from the various words */
  576.     int hflip = data[0] & 0x8000;
  577.     int code = data[0] & 0x7fff;
  578.     int ypos = -(data[1] >> 7);
  579.     int vsize = (data[1] & 0x000f) + 1;
  580.     int xpos = (data[3] >> 6) - 4;
  581.     int hold_next = data[3] & 0x0010;
  582.     int color = data[3] & 0x000f;
  583.  
  584.     /* adjust for height */
  585.     ypos -= vsize * 8;
  586.  
  587.     /* if we've got a hold position from the last MO, use that */
  588.     if (modata->xhold != 1000)
  589.         xpos = modata->xhold;
  590.  
  591.     /* if we've got a hold position for the next MO, set it now */
  592.     if (hold_next)
  593.         modata->xhold = xpos + 16;
  594.     else
  595.         modata->xhold = 1000;
  596.  
  597.     /* adjust the final coordinates */
  598.     xpos &= 0x3ff;
  599.     ypos &= 0x1ff;
  600.     if (xpos >= XDIM) xpos -= 0x400;
  601.     if (ypos >= YDIM) ypos -= 0x200;
  602.  
  603.     /* draw the motion object */
  604.     atarigen_mo_draw_16x8_strip(bitmap, gfx, code, color, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 0);
  605. }
  606.